package cn.chanel.mall.service.impl;

import cn.chanel.mall.admin.vo.AdminOrderVO;
import cn.chanel.mall.admin.vo.AdminUserVO;
import cn.chanel.mall.entity.Cart;
import cn.chanel.mall.entity.Goods;
import cn.chanel.mall.entity.Orders;
import cn.chanel.mall.entity.User;
import cn.chanel.mall.enums.OrderStatusEnum;
import cn.chanel.mall.enums.ResultEnum;
import cn.chanel.mall.exception.MallException;
import cn.chanel.mall.repository.CartRepository;
import cn.chanel.mall.repository.GoodsRepository;
import cn.chanel.mall.repository.OrdersRepository;
import cn.chanel.mall.repository.UserRepository;
import cn.chanel.mall.service.OrderService;
import cn.chanel.mall.utils.EnumUtil;
import cn.chanel.mall.utils.KeyUtil;
import cn.chanel.mall.vo.OrderVO;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

@Slf4j
@Service
public class OrderServiceImpl implements OrderService {
    private static final SimpleDateFormat simpleDateFormat =
            new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Resource
    private OrdersRepository orderRepository;

    @Resource
    private UserRepository userRepository;

    @Resource
    private GoodsRepository goodsRepository;

    @Resource
    private CartRepository cartRepository;

    public OrderVO createOrder(String cartId){
        final Optional<Cart> cartOpt = cartRepository.findById(cartId);
        if(cartOpt.isEmpty()) {
            log.info("createOrder 不能找到购物车条目");
            throw new MallException(ResultEnum.PARAM_ERROR);
        }
        var user = cartOpt.get().getUser();
        var num = cartOpt.get().getNums();
        var goods = cartOpt.get().getGoods();
        if(StringUtils.hasText(user) && StringUtils.hasText(goods) && num > 0){
            final Optional<User> userOpt = userRepository.findById(user);
            final Optional<Goods> goodsOpt = goodsRepository.findById(goods);
            if(userOpt.isPresent() && goodsOpt.isPresent()) {
                val order = new Orders();
                order.setId(KeyUtil.genUniqueKey());
                order.setGoodId(goods);
                order.setNum(num);
                order.setUserId(user);
                val totalMoney = goodsOpt.get().getPrice().multiply(new BigDecimal(num));
                order.setMoney(totalMoney);
                order.setCreateTime(System.currentTimeMillis());
                order.setUpdateTime(System.currentTimeMillis());
                order.setStatus(OrderStatusEnum.ORDER_PAY.getCode());

                Orders save = orderRepository.save(order);
                log.info("createOrder save = {}", save);

                // 清空对应的购物车
                cartRepository.deleteById(cartId);
                return convert(order);
            }else {
                throw new MallException(ResultEnum.USER_INF_ERROR);
            }
        }else {
            throw new MallException(ResultEnum.PARAM_ERROR);
        }
    }

    @Override
    public List<OrderVO> getAllOrderByUser(String user) {
        if(StringUtils.hasText(user)){
            final ArrayList<OrderVO> orderVOS = new ArrayList<>();
            final Optional<User> userOpt = userRepository.findById(user);
            if(userOpt.isEmpty()) {
                throw new MallException(ResultEnum.USER_INF_ERROR);
            }
            final List<Orders> allOrdersByUser = orderRepository.findAllByUserId(user);
            allOrdersByUser.forEach(e -> orderVOS.add(convert(e)));
            return orderVOS;
        }else {
            throw new MallException(ResultEnum.PARAM_ERROR);
        }
    }

    private OrderVO convert(Orders orders) {
        val orderVO = new OrderVO();
        orderVO.setId(orders.getId());
        orderVO.setMoney(orders.getMoney().toString());
        val statusEnum = EnumUtil.getByCode(orders.getStatus(), OrderStatusEnum.class);
        if(statusEnum != null) {
            orderVO.setStatus(statusEnum.getName());
        }else {
            throw new RuntimeException("枚举状态不存在");
        }
        orderVO.setNum(orders.getNum());
        var goodsOpt = goodsRepository.findById(orders.getGoodId());
        goodsOpt.ifPresent(orderVO::setGoods);
        var createDate = new Date(orders.getCreateTime());
        var updateDate = new Date(orders.getUpdateTime());
        orderVO.setCreateTime(simpleDateFormat.format(createDate));
        orderVO.setUpdateTime(simpleDateFormat.format(updateDate));
        return orderVO;
    }

    @Override
    public List<AdminOrderVO> getAllOrders() {
        final List<Orders> ordersList = orderRepository.findAll();
        return getAdminOrderVOS(ordersList);
    }

    @Override
    public List<AdminOrderVO> getAllOrdersByKey(String key) {
        final List<Orders> ordersList = orderRepository.findAllByIdContains(key);
        return getAdminOrderVOS(ordersList);
    }

    private List<AdminOrderVO> getAdminOrderVOS(List<Orders> ordersList) {
        List<AdminOrderVO> adminUserVOS = new ArrayList<>(ordersList.size());
        ordersList.forEach(e -> {
            AdminOrderVO adminOrderVO = new AdminOrderVO();
            adminOrderVO.setOrderVO(convert(e));
            adminOrderVO.setUser(userRepository.getById(e.getUserId()));
            adminUserVOS.add(adminOrderVO);
        });
        return adminUserVOS;
    }

    @Override
    public AdminOrderVO getOrderVOById(String id) {
        final Optional<Orders> orderOpt = orderRepository.findById(id);
        if(orderOpt.isEmpty()){
            throw new MallException(ResultEnum.ORDER_INF_ERROR);
        }
        final AdminOrderVO adminOrderVO = new AdminOrderVO();
        adminOrderVO.setOrderVO(convert(orderOpt.get()));
        adminOrderVO.setUser(userRepository.getById(orderOpt.get().getUserId()));
        adminOrderVO.setStatusCode(orderOpt.get().getStatus());
        return adminOrderVO;
    }

    @Override
    public void updateOrder(String id, int status) {
        final Optional<Orders> orderOpt = orderRepository.findById(id);
        if(orderOpt.isEmpty()){
            throw new MallException(ResultEnum.ORDER_INF_ERROR);
        }
        final Orders orders = orderOpt.get();
        final OrderStatusEnum statusEnum = EnumUtil.getByCode(status, OrderStatusEnum.class);
        if(statusEnum != null) {
            orders.setStatus(statusEnum.getCode());
            orders.setUpdateTime(System.currentTimeMillis());
            orderRepository.save(orders);
        }else {
            throw new MallException(ResultEnum.ORDER_INF_ERROR);
        }
    }
}
